#include "um.rpc.h"

#include "../USS/USSclient.h"
#include "../NS/nameserver.h"
#include "../Headers/types.h"
#include "../Headers/nsr.h"
#include "../Headers/authr.h"
#include "../Headers/log.h"

#include <string>
  
int * changefield_1_svc(Field_UM_RPC * field, struct svc_req * svc) {
  TOB::US us = TOB::US(static_cast<TOB::Nameserver::IP>(field->user.nsip));
  
  Code::Type respond;
  static int result;
  
  int role;
  std::string password, login;
  bool admin, me;
  
  respond = us.getUintByLogin(field->user.username, "role", role);
  if (respond != Code::Okay) {
    result = static_cast<int>(respond);
    TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
    return &result;
  }
  respond = us.getStringByLogin(field->user.username, "password", password);
  if (respond != Code::Okay) {
    result = static_cast<int>(respond);
    TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
    return &result;
  }
  login = field->login;
  admin = (password.compare(field->user.password) == 0);
  me = (admin && login.compare(field->user.username) == 0);
  admin = (admin && static_cast<Role::Type>(role) == Role::Administrator);
  
  std::string fieldName = field->field;
  if (me || admin) {
    if (admin && (fieldName.compare("policy") == 0 || fieldName.compare("role") == 0)) {
      respond = us.updateFieldByLogin(field->login, fieldName, field->value);
      if (respond != Code::Okay) {
        result = static_cast<int>(respond);
        TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
        return &result;
      }
      result = static_cast<int>(Code::Okay);
      TOB::Log::event("UM: изменение поля.");
      return &result;
    }
    if ((fieldName.compare("name") == 0 || fieldName.compare("password") == 0)) {
      respond = us.updateFieldByLogin(field->login, fieldName, field->value);
      if (respond != Code::Okay) {
        result = static_cast<int>(respond);
        TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
        return &result;
      }
      result = static_cast<int>(Code::Okay);
      TOB::Log::event("UM: изменение поля.");
      return &result;
    }
  }
  result = static_cast<int>(Code::UM_Forbidden);
  TOB::Log::error("UM: изменение поля запрешено.");
  return &result;
}

int * adduser_1_svc(UserRec_UM_RPC * user, struct svc_req * svc) {
  TOB::US us = TOB::US(static_cast<TOB::Nameserver::IP>(user->user.nsip));
  
  Code::Type respond;
  static int result;
  
  int role;
  std::string password;
  bool admin;
  
  respond = us.getUintByLogin(user->user.username, "role", role);
  if (respond != Code::Okay) {
    result = static_cast<int>(respond);
    TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
    return &result;
  }
  respond = us.getStringByLogin(user->user.username, "password", password);
  if (respond != Code::Okay) {
    result = static_cast<int>(respond);
    TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
    return &result;
  }
  admin = (password.compare(user->user.password) == 0);
  admin = (admin && static_cast<Role::Type>(role) == Role::Administrator);
  
  if (admin) {
    respond = us.appendRow(user->login, user->password, user->role, user->policy, user->name);
    if (respond != Code::Okay) {
      result = static_cast<int>(respond);
      TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
      return &result;
    }
    result = static_cast<int>(Code::Okay);
    TOB::Log::event("UM: добавлен новый пользователь.");
    return &result;
  }
  result = static_cast<int>(Code::UM_Forbidden);
  TOB::Log::error("UM: добавление нового пользователя запрешено.");
  return &result;
}

int * deleteuser_1_svc(Field_UM_RPC * user, struct svc_req * svc) {
  TOB::US us = TOB::US(static_cast<TOB::Nameserver::IP>(user->user.nsip));
  
  Code::Type respond;
  static int result;
  
  int role;
  std::string password;
  bool admin;
  
  respond = us.getUintByLogin(user->user.username, "role", role);
  if (respond != Code::Okay) {
    result = static_cast<int>(respond);
    TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
    return &result;
  }
  us.getStringByLogin(user->user.username, "password", password);
  if (respond != Code::Okay) {
    result = static_cast<int>(respond);
    TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
    return &result;
  }
  admin = (password.compare(user->user.password) == 0);
  admin = (admin && static_cast<Role::Type>(role) == Role::Administrator);
  
  if (admin) {
    respond = us.deleteRowByLogin(user->login);
    if (respond != Code::Okay) {
      result = static_cast<int>(respond);
      TOB::Log::error("UM: ошибка обращения к хранилищу пользователей.");
      return &result;
    }
    result = static_cast<int>(Code::Okay);
    TOB::Log::event("UM: удален пользователь.");
    return &result;
  }
  result = static_cast<int>(Code::UM_Forbidden);
  TOB::Log::error("UM: удаление пользователя запрешено.");
  return &result;
}
